/** @format */

import React, {ReactElement} from 'react';
import {addBlogWrap, categoryList} from './index.styl';
import {admin as adminApi} from '@/api/admin';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import AlertDialog from '@/view/admin/component/dialog';
import Input from '@material-ui/core/Input';
import trans from '@/api';

interface IProps {
  [propName: string]: any;
}

// 提示框
interface IAlertDialog {
  open: boolean;
  // 默认 top
  vertical?: 'top' | 'bottom';
  // 默认 center
  horizontal?: 'left' | 'center' | 'right';
  // 默认 ''
  msg: string;
  // 默认 info
  severity?: 'error' | 'warning' | 'info' | 'success';
  // 多少秒后消失
  autoHideDuration?: number;
}

// 文件上传框
interface IEditCtrol {
  isShowUploadeditCtrol: boolean;
  fileType: 'html' | 'image' | '';
  isShowSubmitDialog: boolean;
}

interface IState {
  alertDialog: IAlertDialog;
  editCtrol: IEditCtrol;
  article: IArticle;
}

interface IArticle {
  id: number;
  markdown: string;
  category: string;
  title: string;
  audioSrc: string;
}

interface ITools {
  title: string;
  key: 'image/html' | 'save';
}

class Tools extends React.Component<IProps, {menu: ITools[]}> {
  constructor(props: IProps) {
    super(props);
    this.state = {
      menu: [
        {
          key: 'image/html',
          title: '图片/html',
        },
        {
          key: 'save',
          title: '保存',
        },
      ],
    };
  }

  render() {
    const listDom = this.state.menu.map((item, index) => {
      return (
        <span key={index} onClick={() => this.props.operate(item.key)}>
          {item.title}
        </span>
      );
    });
    return <div className={`tools-wrap`}>{listDom}</div>;
  }
}

class GetCategorys extends React.Component<IProps, {categoryDom: ReactElement}> {
  constructor(props: IProps) {
    super(props);
    this.getCategorys = this.getCategorys.bind(this);
    this.state = {
      categoryDom: <></>,
    };
  }

  componentDidMount() {
    this.getCategorys();
  }

  async getCategorys() {
    const [err, Rsp]: any = await trans('getCategory');
    const categoryDom = Rsp.category.map((item: string, index: number) => {
      return (
        <span key={index} onClick={() => this.props.getClickValue(item)}>
          {item}
        </span>
      );
    });

    this.setState({categoryDom: <>{categoryDom}</>});
  }

  render() {
    return <div className={categoryList}>{this.state.categoryDom}</div>;
  }
}

class AddBlog extends React.Component<IProps, IState> {
  private fileInput: React.RefObject<HTMLInputElement>;
  constructor(props: IProps) {
    super(props);
    this.fileInput = React.createRef();
    this.setCategory = this.setCategory.bind(this);
    this.uploadFile = this.uploadFile.bind(this);
    this.alertDialogClose = this.alertDialogClose.bind(this);
    this.closeFileUploadDialog = this.closeFileUploadDialog.bind(this);
    this.submit = this.submit.bind(this);
    this.state = {
      alertDialog: {
        msg: '',
        open: false,
      },
      editCtrol: {
        fileType: '',
        isShowUploadeditCtrol: false,
        isShowSubmitDialog: false,
      },
      article: {
        markdown: '',
        category: '',
        title: '',
        id: 0,
        audioSrc: '',
      },
    };
  }

  async componentDidMount() {
    const id = this.props.match.params && this.props.match.params.id;
    if (!id) {
      return;
    }
    const [errArticle, article]: any = await adminApi.getArticleMarkdown({id});
    if (errArticle) {
      this.setState({
        alertDialog: {
          ...this.state.alertDialog,
          open: true,
          msg: errArticle.msg,
          severity: 'error',
        },
      });
    }
    const newArticle = {
      ...article.article,
      audioSrc: article.article['audio_src'],
    };
    this.setState({article: newArticle});
  }

  alertDialogClose() {
    this.setState({
      alertDialog: {
        ...this.state.alertDialog,
        open: false,
      },
    });
  }

  operate(ops: 'save' | 'image/html') {
    if (ops === 'image/html') {
      this.setState({
        editCtrol: {
          ...this.state.editCtrol,
          isShowUploadeditCtrol: true,
        },
      });
    } else {
      this.setState({
        editCtrol: {
          ...this.state.editCtrol,
          isShowSubmitDialog: true,
        },
      });
    }
  }

  editMarkdown(e: React.ChangeEvent<HTMLTextAreaElement>) {
    const val = e.target.value;
    this.setState({
      article: {
        ...this.state.article,
        markdown: val,
      },
    });
  }

  closeFileUploadDialog() {
    this.setState({
      editCtrol: {
        ...this.state.editCtrol,
        isShowUploadeditCtrol: false,
      },
    });
  }

  async uploadFile() {
    this.setState({
      editCtrol: {
        ...this.state.editCtrol,
        isShowUploadeditCtrol: false,
      },
    });
    const file = this.fileInput.current;
    // 文件类型 后缀
    const val = (file as any).value;
    const reg = /\.(png|jpe?g|gif|html|htm)$/;
    if (!val || !reg.test(val)) {
      this.setState({
        alertDialog: {
          ...this.state.alertDialog,
          open: true,
          msg: '请正确选择文件',
          severity: 'error',
        },
      });
      return;
    }

    const formData = new FormData();
    formData.append('file', (this.fileInput.current as any).files[0]);
    const [uploadFileErr, rsp]: any = await adminApi.uploadFile(formData);
    // 更新失败
    if (uploadFileErr) {
      this.setState({
        alertDialog: {
          ...this.state.alertDialog,
          open: true,
          msg: uploadFileErr.msg,
          severity: 'error',
        },
      });
      return;
    }
    // 上传文件

    const ext = val.substr(val.lastIndexOf('.'));
    this.setState({
      article: {
        ...this.state.article,
        markdown: `${this.state.article.markdown}${!(ext === 'html' || ext === 'htm') ? '!' : ''}[](${rsp.url})`,
      },
      editCtrol: {
        ...this.state.editCtrol,
        isShowUploadeditCtrol: false,
      },
    });
  }

  setCategory(val: string) {
    const resVal = `${this.state.article.category}${this.state.article.category ? '-' : ''}${val}`;
    this.setState({article: {...this.state.article, category: resVal}});
  }

  inputTitleCategory(e: React.ChangeEvent<HTMLInputElement>, type: 'title' | 'category' | 'audio') {
    const val = e.target.value;
    if (type === 'title') {
      this.setState({article: {...this.state.article, title: val}});
    }
    if (type === 'category') {
      this.setState({article: {...this.state.article, category: val}});
    }
    if (type === 'audio') {
      const newArticle = {
        ...this.state.article,
        audioSrc: val,
      };
      this.setState({article: {...this.state.article, audioSrc: val}});
    }
  }

  async submit() {
    const {title, category, markdown} = this.state.article;
    if (!(title && category && markdown)) {
      const msgMap = ['请输入文章标题', '请输入文章分类', '请完成文章内容'];
      const index = [title, category, markdown].indexOf('');
      this.setState({
        alertDialog: {
          ...this.state.alertDialog,
          open: true,
          msg: msgMap[index],
          severity: 'error',
        },
      });
      return;
    }
    this.setState({editCtrol: {...this.state.editCtrol, isShowSubmitDialog: false}});

    const [addBlogErr, addBlogRsp]: any = await adminApi.addBlog(this.state.article);
    this.props.history.push(`/post/${addBlogRsp.id}`);
  }

  render(): JSX.Element {
    return (
      <div className={addBlogWrap}>
        <Tools operate={(val: 'save' | 'image/html') => this.operate(val)} />
        <textarea
          value={this.state.article.markdown}
          onChange={e => {
            this.editMarkdown(e);
          }}
        />
        {
          // 文件上传
        }
        <Dialog
          open={this.state.editCtrol.isShowUploadeditCtrol}
          keepMounted
          onClose={this.closeFileUploadDialog}
          aria-labelledby="alert-dialog-slide-title"
          aria-describedby="alert-dialog-slide-description">
          <DialogTitle id="alert-dialog-slide-title">{'文件上传'}</DialogTitle>
          <DialogContent>
            <input type={'file'} ref={this.fileInput} />
          </DialogContent>
          <DialogActions>
            <Button onClick={this.uploadFile} color="primary">
              确定
            </Button>
            <Button onClick={this.closeFileUploadDialog} color="primary">
              取消
            </Button>
          </DialogActions>
        </Dialog>

        <Dialog
          open={this.state.editCtrol.isShowSubmitDialog}
          keepMounted
          onClose={this.closeFileUploadDialog}
          aria-labelledby="alert-dialog-slide-title"
          aria-describedby="alert-dialog-slide-description">
          <DialogTitle id="alert-dialog-slide-title">{'保存'}</DialogTitle>
          <DialogContent>
            <Input
              fullWidth={true}
              onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                this.inputTitleCategory(e, 'title');
              }}
              type={'text'}
              value={this.state.article.title}
              placeholder={'文章标题'}
            />
            <hr />
            <Input
              fullWidth={true}
              onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                this.inputTitleCategory(e, 'category');
              }}
              type={'text'}
              value={this.state.article.category}
              placeholder={'文章分类'}
            />
            <hr />
            <Input
              fullWidth={true}
              onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                this.inputTitleCategory(e, 'audio');
              }}
              type={'text'}
              value={this.state.article.audioSrc}
              placeholder={'文章音频'}
            />
            <hr />
            <GetCategorys getClickValue={(value: string) => this.setCategory(value)} />
          </DialogContent>
          <DialogActions>
            <Button onClick={this.submit} color="primary">
              确定
            </Button>
            <Button
              onClick={() => {
                this.setState({editCtrol: {...this.state.editCtrol, isShowSubmitDialog: false}});
              }}
              color="primary">
              取消
            </Button>
          </DialogActions>
        </Dialog>
        <AlertDialog {...this.state.alertDialog} onClose={this.alertDialogClose} />
      </div>
    );
  }
}

export default AddBlog;
